#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <cassert>
#include <fstream>
#include "../comm/util.hpp"
#include "../comm/log.hpp"

namespace ns_model
{
    using namespace ns_util;
    using namespace ns_log;

    struct Question
    {
        std::string number;    //题目的编号
        std::string title;     //题目的名称
        std::string star;      //题目的难度
        int cpu_limit;         //题目所用CPU的时间限制
        int mem_limit;         //题目所用内存的时间限制
        std::string desc;      //题目的描述
        std::string header;    //题目的预设代码
        std::string test;      //题目的测试用例
    };

    const std::string question_list = "./all_questions/question.list";
    const std::string questions_path = "../oj_server/all_questions/";
    
    class model
    {
    private:
        std::unordered_map<std::string, Question> Questions;
    public:
        model()
        {
            assert(LoadAllQuestions(question_list));
        }

        bool LoadAllQuestions(const std::string& question_list)
        {
            std::ifstream ifs(question_list);
            if(!ifs.is_open())
            {
                LOG(FATAL) << "题库文件打开失败" << std::endl;
                return false;
            }
            std::string line;
            while(getline(ifs, line))
            {
                std::vector<std::string> content;
                StringUtil::SplitString(line, &content, " ");
                if(content.size() != 5)
                {
                    LOG(WARNING) << "加载部分题目失败" << std::endl;
                    continue;
                }
                Question q;
                q.number = content[0];
                q.title = content[1];
                q.star = content[2];
                q.cpu_limit = atoi(content[3].c_str());
                q.mem_limit = atoi(content[4].c_str());
                
                std::string path = questions_path;
                path += q.number;
                path += "/";

                FileUtil::ReadFile(path + "desc.txt", &q.desc, true);
                FileUtil::ReadFile(path + "header.cpp", &q.header, true);
                FileUtil::ReadFile(path + "test.cpp", &q.test, true);
                
                Questions.insert({q.number, q});
            }
            ifs.close();
            return true;
        }

        bool GetAllQuestions(std::vector<Question>* out)
        {
            if(Questions.empty())
            {
                LOG(FATAL) << "题目列表为空" << std::endl;
                return false;
            }
            for(auto& q : Questions)
            {
                out->push_back(q.second);
            }
            return true;
        }

        bool GetOneQuestion(const std::string& num, Question* out)
        {
            const auto& iter = Questions.find(num);
            if(iter == Questions.end())
            {
                LOG(INFO) << "你所请求的题目不存在" << std::endl;
                return false;
            }            
            *out = iter->second;

            return true;
        }

        ~model()
        {}
    };
}
